package com.jplus.core.core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import com.jplus.core.core.abstracts.BeanDefinitions;
import com.jplus.core.core.abstracts.BeanFactory;
import com.jplus.core.core.beans.BeanDefinition;
import com.jplus.core.core.beans.BeanKey;
import com.jplus.core.fault.InitializationError;
import com.jplus.core.utill.JUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 初始化 代理框架<br>
 * 
 * @author Yuanqy
 */
public class ProxyHandle {
	private Logger log = LoggerFactory.getLogger(ProxyHandle.class);
	private BeanDefinitions beanDefinition;
	// 原始类，代理类集合
	private Map<BeanKey, List<BeanKey>> proxyPlugin = new ConcurrentHashMap<>();

	public List<BeanKey> getProxyList(BeanKey curBean) {
		return proxyPlugin.get(curBean);
	}

	public void addProxy(BeanKey curBean, BeanKey proxyBean) {
		List<BeanKey> list = JUtil.notNullDef(proxyPlugin.get(curBean), new ArrayList<BeanKey>());
		list.add(proxyBean);
		proxyPlugin.put(curBean, list);
	}

	/**
	 * @param beanDefMap
	 */
	public ProxyHandle(BeanDefinitions beanDefinition, BeanFactory beanFactory) {
		this.beanDefinition = beanDefinition;
		this.proxyPlugin = new HashMap<>();
	}

	/**
	 * 获取 ClassScanner
	 */
	public ProxyHandle init() {
		try {
			createProxyMap();
			repeatAndSort();
		} catch (Exception e) {
			log.error("InitializationError:", e);
			throw new InitializationError("InitializationError!", e);
		}
		return this;
	}

	// ==================================================================
	private void createProxyMap() throws Exception {
		List<BeanDefinition> list = beanDefinition.listSortBeanDefinitions();
		for (BeanDefinition bean : list) {
			if (bean.isProxy()) {
				for (BeanKey key : bean.getProxyList()) {// 获取代理链
					addProxy(bean.getBeanKey(), key);
				}
			}
		}
	}

	// ==================================================================

	private void repeatAndSort() {
		log.info("[AOP]:{}", proxyPlugin.size());
		for (Entry<BeanKey, List<BeanKey>> pps : proxyPlugin.entrySet()) {
			log.info("[AOP]:" + pps.getKey());
			List<BeanKey> list = pps.getValue();
			{
				// Repeat
				LinkedHashSet<BeanKey> set = new LinkedHashSet<BeanKey>(list.size());
				set.addAll(list);
				list.clear();
				list.addAll(set);
				// Sort
				Collections.sort(list);
			}
			proxyPlugin.put(pps.getKey(), list);
			for (BeanKey proxy : list) {
				log.info("\t>> " + proxy);
			}
		}
	}

}
